#include <iterator>
#include "MarkupSTL.h"
#include "global.h"
#include "cmd.h"
#include "Game.h"
#include "RedisClient.h"
#include "Logic.h"
#include "json.h"
#include "globalExtern.h"
#include "Host.h"
#include "NodeServer.h"


int split_str(const char* ps_str, char* ps_sp, vector<std::string> &v_ret)
{
	char* ps_temp;
	char* p;
	int i_len = (int)strlen(ps_str);
	std::string st_str;
	ps_temp = new char[i_len + 2];
	snprintf(ps_temp, i_len + 1, "%s", ps_str);
	char *last = NULL;    p = strtok_r(ps_temp, ps_sp, &last);
	if (NULL == p)
	{
		delete ps_temp;
		return 0;
	}
	st_str = (std::string)p;
	v_ret.push_back(st_str);
	while (NULL != (p = strtok_r(NULL, ps_sp, &last)))
	{
		st_str = (std::string)p;
		v_ret.push_back(st_str);
	}
	delete ps_temp;
	return 0;
}



CGameServer::CGameServer()
{
}

CGameServer::~CGameServer()
{
}

bool CGameServer::InitGame()
{
	char conf_path[128] = "./config.xml";
	if (!ReadCommonConf(conf_path))
	{
		log_boot("InitGame ReadCommonConf failed. path:[%s]", conf_path);
		return false;
	}

	m_isLeader = false;
	m_score = 0;
	return true;
}

int CGameServer::OnBYTimeOut(int Timerid)
{
	return 0;
}

bool CGameServer::ReadCommonConf(const char* strxml)
{
	CMarkupSTL  markup;
	if (!markup.Load(strxml))
	{
		log_error("Load xml %s failed", strxml);
		return false;
	}

	if (!markup.FindElem("application"))
	{
		log_error("Not Found Elem [application] in xml[%s]", strxml);
		return false;
	}

	if (!markup.IntoElem())
	{
		log_error("IntoElem [application] failed.");
		return false;
	}


	if (!markup.FindElem("service_provider"))
	{
		log_error("Not Found Elem [service_provider] in xml[%s]", strxml);
		return false;
	}
	else
	{
		markup.IntoElem();
		while (markup.FindElem("item"))
		{
			std::string service_name;
			int server_type, alloc_type, active_count, switch_time;
			service_name = markup.GetAttrib("name");
			server_type = atoi(markup.GetAttrib("server_type").c_str());
			alloc_type = atoi(markup.GetAttrib("alloc_type").c_str());
			if (ALLOC_MOD == alloc_type)
				alloc_type = ALLOC_MOD;
			else
				alloc_type = ALLOC_RANDOM;
			active_count = atoi(markup.GetAttrib("active_count").c_str());
			switch_time = atoi(markup.GetAttrib("switch_millisecond").c_str());

			ProviderItem* pItem = GetProviderConfItem(server_type);
			if (NULL == pItem)
			{
				pItem = new ProviderItem();
			}
			pItem->service_name = service_name;
			pItem->server_type = server_type;
			pItem->alloc_type = alloc_type;
			pItem->active_count = active_count;
			pItem->switch_time = switch_time;
	
			m_providerConfList[pItem->server_type] = pItem;

			log_debug("add provider_item name=%s, server_type=%d, alloc_type=%d, active_count=%d, switch_time=%d, ",
				pItem->service_name.c_str(), pItem->server_type, 
				pItem->alloc_type, pItem->active_count, pItem->switch_time);
		}
		markup.OutOfElem();
	}



	if (!markup.FindElem("service_requestor"))
	{
		log_error("Not Found Elem [service_requestor] in xml[%s]", strxml);
		return false;
	}
	else
	{
		markup.IntoElem();
		while (markup.FindElem("item"))
		{
			std::string requestor_name, request_service_str;
			int server_type;
			requestor_name = markup.GetAttrib("name");
			server_type = atoi(markup.GetAttrib("server_type").c_str());
			request_service_str = markup.GetAttrib("request_service");
			RequestorItem* pItem = GetRequestorConfItem(server_type);
			if (NULL == pItem)
			{
				pItem = new RequestorItem();
			}

			pItem->requestor_name = markup.GetAttrib("name");
			pItem->server_type = atoi(markup.GetAttrib("server_type").c_str());
			pItem->request_service_str = markup.GetAttrib("request_service");
			this->ParseConnStr(pItem->request_service_str, pItem->reqServicItems);
			

			m_requestorConfList[pItem->server_type] = pItem;

			log_debug("add requestor_item name=%s, server_type=%d, request_service=%s  ,",
				pItem->requestor_name.c_str(), pItem->server_type, pItem->request_service_str.c_str());
		}
		markup.OutOfElem();
	}
	log_debug("CGameServer ReadCommonConf succ!!");

	return true;
}

int CGameServer::ParseConnStr(std::string& items_str, std::vector<int>& vec_items)
{
	vec_items.clear();
	char pattern[4] = ",";
	std::vector<std::string>  str_vec;
	split_str(items_str.c_str(), pattern, str_vec);
	for (int i = 0; i < str_vec.size(); i++)
	{
		int num = atoi(str_vec[i].c_str());
		if (num > 0)
			vec_items.push_back(num);
	}
	return 0;
}

int CGameServer::ProcessPacket(SocketHandler * pHandler, NETInputPacket* inputPkg)
{
	int cmd = inputPkg->GetCmdType();
	switch (cmd)
	{
	case SERVICEMANAGER_SRV_RETIRE_SERVICE:
		ProcRetireService(pHandler, inputPkg);
		break;
	case SERVICEMANAGER_SRV_RELOAD_CONF:
		ProcLoadConf(pHandler, inputPkg);
		break;

	case SERVICEMANAGER_SRV_ADD_SCORE:
		ProcAddScore(pHandler, inputPkg);
		break;
	case SERVICEMANAGER_SRV_REPORT_SCORE:
		ProcReportScore(pHandler, inputPkg);
		break;
	case SERVICEMANAGER_SRV_OFFLINE:
		ProcSMOffline(pHandler, inputPkg);
		break;
	case SERVICEMANAGER_SRV_VOTE_LEADER:
		ProcVoteLeader(pHandler, inputPkg);
		break;
	case SERVICEMANAGER_SRV_SYN_PROVIDER_DATA:
		ProcSynProviderData(pHandler, inputPkg);
		break;
	case SERVICEMANAGER_SRV_REQ_SYN_PROVIDER_DATA:
		ProcReqProviderData(pHandler, inputPkg);
		break;
	default:
		log_error("cmd=0x%x,  svid=%d, err no proc", cmd, pHandler->getId());
		break;
	}
	return 0;
}

int CGameServer::ProcRetireService(SocketHandler * pHandler, NETInputPacket* inputPkg)
{
	if (!m_isLeader)
	{
		log_error("svid=%d, m_score=%d, m_isLeader=%d,", TGlobal::_svid, m_score, m_isLeader);
		return 0;
	}

	int provider_type = inputPkg->ReadInt();
	int provider_svid = inputPkg->ReadInt();
	
	log_debug("sender svid=%d, stype=%d, provider_type=%d,  provider_svid=%d", 
		pHandler->getId(), pHandler->getType(), provider_type, provider_svid);

	int ret = 0;
	ProviderItem* providerConf = GetProviderConfItem(provider_type);
	if (NULL == providerConf)
	{
		ret = 1;  //err, no service

		return 0;
	}

	ret = 2;  //not in active
	ProviderMap& idleItems = m_idleProviderMapTypeList[provider_type];
	ProviderVect& activeItems = m_activeProviderTypeList[provider_type];
	for (int i = 0; i < activeItems.size(); i++)
	{
		if (NULL != activeItems[i] && 
			activeItems[i]->svid == provider_svid)
		{//find retire svid
			if (idleItems.size() <= 0)
			{// no more idle service
				ret = 3;// 
			}
			else
			{
				ProviderMap::iterator iter_ = idleItems.begin();
				ServerData* pServer = iter_->second;
				idleItems.erase(iter_);
				idleItems[provider_svid] = activeItems[i];  //add retire svid
				
				activeItems[i] = pServer;
				ret = 0; // retire success
			}
			break;
		}
	}

	log_error("svid=%d, m_score=%d, m_isLeader=%d,  provider_type=%d, provider_svid=%d,  ret=%d,  ", 
		TGlobal::_svid, m_score, m_isLeader, provider_type, provider_svid, ret);
	if (0 == ret)
	{
		this->PublishService(provider_type);
	}

	return 0;
}

ProviderItem* CGameServer::GetProviderConfItem(int type)
{
	ProviderItem* pItem = NULL;
	ProviderConfList::iterator iter = m_providerConfList.find(type);
	if (iter != m_providerConfList.end())
	{
		pItem = iter->second;
	}
	return pItem;
}

RequestorItem* CGameServer::GetRequestorConfItem(int type)
{
	RequestorItem* pItem = NULL;
	RequestorConfList::iterator iter = m_requestorConfList.find(type);
	if (iter != m_requestorConfList.end())
	{
		pItem = iter->second;
	}
	return pItem;
}

int CGameServer::ClientRegister(ServerData* pItem)
{
	ProviderItem* pProvider = GetProviderConfItem(pItem->type);
	RequestorItem* pRequestor = GetRequestorConfItem(pItem->type);
	
	if (NULL != pProvider)
	{
		this->RegisterProvider(pItem, pProvider);
	}

	if (NULL != pRequestor)
	{
		this->RegisterRequestor(pItem, pRequestor);
	}


	return 0;
}

int CGameServer::RegisterProvider(ServerData* pData, ProviderItem* pProvider)
{
	int server_type = pData->type;
	int svid = pData->svid;

	ProviderMap& idleItems = m_idleProviderMapTypeList[server_type];
	ProviderVect& activeItems = m_activeProviderTypeList[server_type];
	bool  isAdded = false;
	
	ProviderMap::iterator iter = idleItems.find(svid);
	if (iter != idleItems.end())
	{
		isAdded = true;
		iter->second = pData;
	}

	
	for (int i = 0; i < activeItems.size(); i++)
	{
		ServerData* pActiveItem = activeItems[i];
		if (NULL != pActiveItem && activeItems[i]->svid == pData->svid)
		{
			activeItems[i] = pData;
			isAdded = true;
		}
	}

	if (!isAdded)
	{// add idle first
		idleItems[svid] = pData;
	}

	if (!m_isLeader)
	{
		log_error("svid=%d, m_score=%d, m_isLeader=%d, provider_type=%d, provider_svid=%d,",
			TGlobal::_svid, m_score, m_isLeader, server_type, svid);

		ReqLeaderProviderData();
		return 0;
	}
	log_error("svid=%d, m_score=%d, m_isLeader=%d, provider_type=%d, provider_svid=%d,", 
		TGlobal::_svid, m_score, m_isLeader, server_type, svid);

	int active_count = GetActiveProviderCount(activeItems);
	if ((active_count < pProvider->active_count) && (idleItems.size() > 0))
	{// less than require
		int count = pProvider->active_count - active_count;
		if (count > idleItems.size())
			count = idleItems.size();

		for (int i = 0; i < count; i++)
		{
			ProviderMap::iterator iter_ = idleItems.begin();
			ServerData* pBack = iter_->second;
			idleItems.erase(iter_);
			AddActiveProvider(activeItems, pBack);
		}

#if 1  //test code
		std::string str_log;
		char str_buf[64] = { 0 };
		snprintf(str_buf, 63, " provider_type=%d, provider_count=%d, svid=[", server_type, pProvider->active_count);
		str_log += str_buf;
		for (int i = 0; i < activeItems.size(); i++)
		{
			ServerData* pServer = activeItems[i];
			int svid = 0;
			if (NULL == pServer)
				svid = 0;
			else
				svid = pServer->svid;

			snprintf(str_buf, 63, " %d, ", svid);
			str_log += str_buf;
		}
		str_log += "]";

		log_error(" %s ", str_log.c_str());
#endif

		if (GetActiveProviderCount(activeItems) >= pProvider->active_count)
		{// notify all the requestor
			this->PublishService(server_type);
		}
	}

	return 0;
}

int CGameServer::RegisterRequestor(ServerData* pData, RequestorItem* pRequestor)
{
	int server_type = pData->type;
	RequestorVect& requestor_items = m_requestorTypeList[server_type];
	bool  isAdded = false;
	for (int i = 0; i < requestor_items.size(); i++)
	{
		if (requestor_items[i]->svid == pData->svid)
		{
			isAdded = true;
		}
	}

	if (!isAdded)
	{
		requestor_items.push_back(pData);
		log_error("svid=%d, m_score=%d, m_isLeader=%d, Requestor_type=%d, Requestor_svid=%d,",
			TGlobal::_svid, m_score, m_isLeader, server_type, pData->svid);

		if (!m_isLeader)
		{
			return 0; 
		}	
		
		// push the service to the new Requestor
		this->FindRequestorAllService(server_type, pData->svid);
	}
	return 0;
}


int CGameServer::ClientHandlerClose(SocketHandler* pHandler)
{
	int server_type = pHandler->getType();
	int server_id = pHandler->getId();
	ProviderItem* pProvider = GetProviderConfItem(server_type);
	RequestorItem* pRequestor = GetRequestorConfItem(server_type);

	if (NULL != pProvider)
	{
		this->ProviderHandlerClose(pProvider, server_id, server_type);
	}

	if (NULL != pRequestor)
	{
		this->RequestorHandlerClose(pRequestor, server_id, server_type);
	}

	return 0;
}



int CGameServer::ProviderHandlerClose(ProviderItem* pProvider, int server_id, int server_type)
{
	ProviderMap& idleItems = m_idleProviderMapTypeList[server_type];
	ProviderVect& activeItems = m_activeProviderTypeList[server_type];

	idleItems.erase(server_id);
	bool isAddProvider = false;
	for (size_t i = 0; i < activeItems.size(); i++)
	{
		if (NULL != activeItems[i] && 
			activeItems[i]->svid == server_id)
		{
			activeItems[i] = NULL;

			if (!m_isLeader)
				break;
			
			if (idleItems.size() > 0)
			{// alloc new idle provider
				ProviderMap::iterator iter_ = idleItems.begin();
				ServerData* pServer = iter_->second;
				idleItems.erase(iter_);

				activeItems[i] = pServer;
				isAddProvider = true;
			}
			break;
		}
	}

	log_error("svid=%d, m_score=%d, m_isLeader=%d,  provider_type=%d, provider_svid=%d,   ",
		TGlobal::_svid, m_score, m_isLeader, server_type, server_id);
		
		
	if (!m_isLeader)
		return 0;


#if 1  //test code
	std::string str_log;
	char str_buf[64] = { 0 };
	snprintf(str_buf, 63, " provider_type=%d, provider_count=%d, svid=[", server_type, pProvider->active_count);
	str_log += str_buf;
	for (int i = 0; i < activeItems.size(); i++)
	{
		ServerData* pServer = activeItems[i];
		int svid = 0;
		if (NULL == pServer)
			svid = 0;
		else
			svid = pServer->svid;

		snprintf(str_buf, 63, " %d, ", svid);
		str_log += str_buf;
	}
	str_log += "]";

	log_error(" %s ", str_log.c_str());
#endif


	if (isAddProvider &&
		(GetActiveProviderCount(activeItems) >= pProvider->active_count))
	{
		this->PublishService(server_type);
	}

	return 0;
}

int CGameServer::RequestorHandlerClose(RequestorItem* pRequestor, int server_id, int server_type)
{
	RequestorVect& requestor_items = m_requestorTypeList[server_type];

	for (size_t i = 0; i < requestor_items.size(); i++)
	{
		if (requestor_items[i]->svid == server_id)
		{
			requestor_items.erase(requestor_items.begin() + i);
			break;
		}
	}

	return 0;
}

int CGameServer::PublishService(int provider_type)
{
	ProviderItem* providerConf = GetProviderConfItem(provider_type);
	ProviderVect& activeItems = m_activeProviderTypeList[provider_type];
	
	int active_count = GetActiveProviderCount(activeItems);
	if (active_count < providerConf->active_count)
	{
		return 0;
	}	

	this->ResortProviderVect(activeItems);
	this->NotifyRequestorNewService(provider_type);

	this->SendAllProviderDataToFollower();

#if 1  //test code
	std::string str_log;
	char str_buf[64] = { 0 };
	snprintf(str_buf, 63, " provider_type=%d, provider_count=%d, svid=[", provider_type, providerConf->active_count);
	str_log += str_buf;
	for (int i = 0; i <activeItems.size(); i++)
	{
		snprintf(str_buf, 63, " %d, ", activeItems[i]->svid);
		str_log += str_buf;
	}
	str_log += "]";

	log_error(" %s ", str_log.c_str());
#endif


	return 0;
}


int CGameServer::NotifyRequestorNewService(int provider_type)
{
	ProviderItem* providerConf = GetProviderConfItem(provider_type);
	ProviderVect& activeItems = m_activeProviderTypeList[provider_type];

	if ((NULL == providerConf) || (activeItems.size() < providerConf->active_count))
		return 0;

	NETOutputPacket outPkg;
	outPkg.Begin(SERVICEMANAGER_SRV_PUBLISH_SERVICE);
	outPkg.WriteInt(providerConf->server_type);
	outPkg.WriteInt(providerConf->alloc_type);
	outPkg.WriteInt(providerConf->switch_time);
	outPkg.WriteInt(providerConf->active_count);
	for (size_t i = 0; i < providerConf->active_count; i++)
	{
		outPkg.WriteInt(activeItems[i]->svid);
	}
	outPkg.End();

	RequestorTypeList::iterator  iter_req = m_requestorTypeList.begin();
	for (; iter_req != m_requestorTypeList.end(); iter_req++)
	{
		int req_type = iter_req->first;
		RequestorItem* pReqConf = GetRequestorConfItem(req_type);
		RequestorVect&  reqItems = iter_req->second;
		if (NULL == pReqConf || pReqConf->reqServicItems.size() <= 0)
		{// current req_type  no service 
			continue;
		}

		bool isRequire = false;
		for (size_t i = 0; i < pReqConf->reqServicItems.size(); i++)
		{
			if (provider_type == pReqConf->reqServicItems[i])
			{
				isRequire = true;
			}
		}

		if (isRequire)
		{
			for (int i = 0; i < reqItems.size(); i++)
			{
				ServerData* pRequestor = reqItems[i];
				if (NULL != pRequestor->pHandler)
					pRequestor->pHandler->Send(&outPkg);
			}
		}
	}

	//also notify all the provider
	this->m_pHost->BroadcastMessage(&outPkg, provider_type);
	return 0;
}

int CGameServer::FindRequestorAllService(int requestor_type, int svid)
{
	RequestorItem* pReqConf = GetRequestorConfItem(requestor_type);
	if (NULL == pReqConf || pReqConf->reqServicItems.size() <= 0)
	{// current req_type  no service 
		return 0;
	}
	ServerData* pRequestor = NULL;
	RequestorVect&  reqItems = m_requestorTypeList[requestor_type];
	for (int i = 0; i < reqItems.size(); i++)
	{
		if (svid == reqItems[i]->svid)
			pRequestor = reqItems[i];
	}
	if (NULL == pRequestor || NULL == pRequestor->pHandler)
		return 0;


	for (int i = 0; i < pReqConf->reqServicItems.size(); i++)
	{
		int provider_type = pReqConf->reqServicItems[i];
		ProviderItem* providerConf = GetProviderConfItem(provider_type);
		ProviderVect& activeItems = m_activeProviderTypeList[provider_type];
		int active_count = GetActiveProviderCount(activeItems);
		if ((NULL == providerConf) || (active_count < providerConf->active_count))
			continue;

		NETOutputPacket outPkg;
		outPkg.Begin(SERVICEMANAGER_SRV_PUBLISH_SERVICE);
		outPkg.WriteInt(providerConf->server_type);
		outPkg.WriteInt(providerConf->alloc_type);
		outPkg.WriteInt(providerConf->switch_time);
		outPkg.WriteInt(providerConf->active_count);
		for (size_t i = 0; i < providerConf->active_count; i++)
		{
			outPkg.WriteInt(activeItems[i]->svid);
		}
		outPkg.End();
		pRequestor->pHandler->Send(&outPkg);
	}

	return 0;
}


int CGameServer::ProcLoadConf(SocketHandler * pHandler, NETInputPacket* inputPkg)
{
	char conf_path[128] = "./config.xml";
	this->ReadCommonConf(conf_path);

	if (!m_isLeader)
		return 0;

	log_error("self_svid=%d, m_score=%d,  m_isLeader=%d,  ", TGlobal::_svid, m_score, m_isLeader);

	ProviderConfList::iterator iter = m_providerConfList.begin();
	for (; iter != m_providerConfList.end(); iter++)
	{
		int provider_type = iter->first;
		ProviderItem* providerConf = iter->second;
		

		ProviderMap& idleItems = m_idleProviderMapTypeList[provider_type];
		ProviderVect& activeItems = m_activeProviderTypeList[provider_type];
		this->ResortProviderVect(activeItems);
		int active_count = GetActiveProviderCount(activeItems);
		if (active_count < providerConf->active_count)
		{
			int count = providerConf->active_count - active_count;
			if (idleItems.size() < count)
				count = idleItems.size();

			for (int i = 0; i<count; i++)
			{
				ProviderMap::iterator iter_ = idleItems.begin();
				ServerData* pBack = iter_->second;
				idleItems.erase(iter_);

				AddActiveProvider(activeItems, pBack);
			}

			if (GetActiveProviderCount(activeItems) >= providerConf->active_count)
			{// notify all the requestor
				this->PublishService(provider_type);
			}
		}
		else if (active_count > providerConf->active_count)
		{
			int count = active_count - providerConf->active_count;
			for (size_t i = 0; i < count; i++)
			{
				ServerData* pBack = activeItems.back();
				activeItems.pop_back();
				idleItems[pBack->svid] = pBack;
			}

			if (GetActiveProviderCount(activeItems) >= providerConf->active_count)
			{// notify all the requestor
				this->PublishService(provider_type);
			}
		}
	}
	return 0;
}


int CGameServer::GetActiveProviderCount(ProviderVect& activeItems)
{
	int active_count = 0;
	for (int i = 0; i < activeItems.size(); i++)
	{
		if (NULL != activeItems[i])
			active_count++;
	}
	return active_count;
}

bool comparebysvid(const ServerData* pa, const ServerData* pb)
{
	if (pa && pb)
	{
		return pa->svid < pb->svid;
	}
	else if (pa)
	{
		return true;
	}

	return false;
}

void CGameServer::AddActiveProvider(ProviderVect& activeItems, ServerData* pServer)
{
	bool isAdd = false;
	for (int i = 0; i < activeItems.size(); i++)
	{
		if (NULL == activeItems[i])
		{
			activeItems[i] = pServer;
			isAdd = true;
			break;
		}
	}
	if (!isAdd)
	{
		activeItems.push_back(pServer);
	}

	std::sort(activeItems.begin(), activeItems.end(), comparebysvid);
}


void CGameServer::ResortProviderVect(ProviderVect& activeItems)
{
	ProviderVect newVect;
	for (int i = 0; i < activeItems.size(); i++)
	{
		if (NULL != activeItems[i])
			newVect.push_back(activeItems[i]);
	}

	activeItems = newVect;
}


int CGameServer::SendAllProviderDataToFollower()
{	
	NETOutputPacket outPkg;
	outPkg.Begin(SERVICEMANAGER_SRV_SYN_PROVIDER_DATA);
	outPkg.WriteInt(TGlobal::_svid);
	outPkg.WriteInt(m_score);

	outPkg.WriteInt(m_activeProviderTypeList.size());
	ProviderTypeList::iterator iter = m_activeProviderTypeList.begin();
	for (; iter != m_activeProviderTypeList.end(); iter++)
	{
		int type = iter->first;
		outPkg.WriteInt(type);

		ProviderVect& activeItems = iter->second;
		outPkg.WriteInt(activeItems.size());
		for (int i = 0; i < activeItems.size(); i++)
		{
			ServerData* pServer = activeItems[i];
			if (NULL == pServer)
				outPkg.WriteInt(0);
			else
				outPkg.WriteInt(pServer->svid);
		}

#if 1  //test code
		std::string str_log;
		char str_buf[64] = { 0 };
		snprintf(str_buf, 63, " provider_type=%d, active_count=%d,  ", type, activeItems.size());
		str_log += str_buf;
		for (int i = 0; i < activeItems.size(); i++)
		{
			ServerData* pServer = activeItems[i];
			int svid = 0;
			if (NULL == pServer)
				svid = 0;
			else
				svid = pServer->svid;

			snprintf(str_buf, 63, " [idx=%d,svid=%d,],", i, svid);
			str_log += str_buf;
		}

		log_error(" %s ", str_log.c_str());
#endif

	}
	outPkg.End();

	this->m_pHost->BroadcastMessage(&outPkg, SERVER_TYPE_SERVICE_MANAGER);
	return 0;
}


int CGameServer::ReqLeaderProviderData()
{
	NETOutputPacket outPkg;
	outPkg.Begin(SERVICEMANAGER_SRV_REQ_SYN_PROVIDER_DATA);
	outPkg.End();

	this->m_pHost->BroadcastMessage(&outPkg, SERVER_TYPE_SERVICE_MANAGER);
	return 0;
}

int CGameServer::ProcAddScore(SocketHandler* pHandler, NETInputPacket* inputPkg)
{
	int t_score = inputPkg->ReadInt();
	int srv_count = inputPkg->ReadInt();
	int svid = inputPkg->ReadInt();

	if (TGlobal::_svid == svid)
	{// 
		return 0;
	}

	if (0 == m_score)
	{// new create node
		m_score += t_score;
		if (srv_count <= 1)
		{//the first one
			m_isLeader = true;
			m_score += (rand() % 10 + 10);
		}
		else
		{// more than one
			m_isLeader = false;
		}
	}
	else
	{// old node
		m_score += t_score;
	}

	log_error("svid=%d, m_score=%d, t_score=%d, m_isLeader=%d,  srv_count=%d,",
		TGlobal::_svid, m_score, t_score, m_isLeader, srv_count);

	this->ReportScoreToPeers();


	if (m_isLeader)
	{
		this->SendAllProviderDataToFollower();
	}

	return 0;
}


int CGameServer::ReportScoreToPeers()
{
	NETOutputPacket outPkg;
	outPkg.Begin(SERVICEMANAGER_SRV_REPORT_SCORE);
	outPkg.WriteInt(TGlobal::_svid);
	outPkg.WriteInt(this->m_score);
	outPkg.End();

	this->m_pHost->BroadcastMessage(&outPkg, SERVER_TYPE_SERVICE_MANAGER);

	return 0;
}

int CGameServer::ProcReportScore(SocketHandler* pHandler, NETInputPacket* inputPkg)
{
	int svid = inputPkg->ReadInt();
	int score = inputPkg->ReadInt();

	if (svid == TGlobal::_svid)
		return 0; // skip self

	
	bool isNeedReport = false;
	SMList::iterator iter = m_smList.find(svid);
	if (iter == m_smList.end())
	{
		isNeedReport = true;
	}
	else
	{
		int old_score = iter->second.score;
		if (old_score != score)
			isNeedReport = true;
	}

	SMITem item;
	item.svid = svid;
	item.score = score;
	m_smList[svid] = item;

	this->VoteLeader();

	log_error("self_svid=%d, m_score=%d, svid=%d, score=%d, ", TGlobal::_svid, m_score, svid, score);

	if (isNeedReport)
	{
		this->ReportScoreToPeers();
	}

	if (m_isLeader)
	{
		this->SendAllProviderDataToFollower();
	}

	return 0;
}


int CGameServer::ProcSMOffline(SocketHandler* pHandler, NETInputPacket* inputPkg)
{
	int type = inputPkg->ReadInt();
	int svid = inputPkg->ReadInt();

	SMList::iterator iter = m_smList.find(svid);
	if (iter != m_smList.end())
	{
		SMITem item = iter->second;
		m_smList.erase(iter);
	}


	log_debug("offline  type=%d, svid=%d, ", type, svid);
	this->VoteLeader();
	return 0;
}


int CGameServer::VoteLeader()
{
	bool isLeader = true;
	SMList::iterator iter = m_smList.begin();
	for (; iter != m_smList.end( ); iter++)
	{
		SMITem& item = iter->second;
		if (item.score > m_score &&
			item.svid != TGlobal::_svid)
		{
			isLeader = false;
		}
	}

	log_error("svid=%d, m_score=%d, isLeader=%d,  m_smList.size=%d,",
		TGlobal::_svid, m_score, isLeader, m_smList.size());

	if (isLeader)
	{
		m_isLeader = true;
		
		NETOutputPacket outPkg;
		outPkg.Begin(SERVICEMANAGER_SRV_VOTE_LEADER);
		outPkg.WriteInt(TGlobal::_svid);
		outPkg.WriteInt(m_score);
		outPkg.End();
		this->m_pHost->BroadcastMessage(&outPkg, SERVER_TYPE_SERVICE_MANAGER);
	}
	else
	{
		m_isLeader = false;
	}
	return 0;
}


int CGameServer::ProcVoteLeader(SocketHandler* pHandler, NETInputPacket* inputPkg)
{
	int svid = inputPkg->ReadInt();
	int score = inputPkg->ReadInt();

	if (svid == TGlobal::_svid)
		return 0; // skip self

	SMITem item;
	item.svid = svid;
	item.score = score;
	m_smList[svid] = item;

	log_error("self_svid=%d, m_score=%d,  svid=%d, score=%d, ", TGlobal::_svid, m_score, svid, score);

	if (m_score > score)
	{
		m_isLeader = true;

		NETOutputPacket outPkg;
		outPkg.Begin(SERVICEMANAGER_SRV_VOTE_LEADER);
		outPkg.WriteInt(TGlobal::_svid);
		outPkg.WriteInt(m_score);
		outPkg.End();
		this->m_pHost->BroadcastMessage(&outPkg, SERVER_TYPE_SERVICE_MANAGER);
	}
	else  if (m_score == score)
	{
		m_score += ((rand() % 10) + 10);
		m_isLeader = true;

		log_debug("self_svid=%d, m_score=%d,   new_add ", TGlobal::_svid, m_score);

		NETOutputPacket outPkg;
		outPkg.Begin(SERVICEMANAGER_SRV_VOTE_LEADER);
		outPkg.WriteInt(TGlobal::_svid);
		outPkg.WriteInt(m_score);
		outPkg.End();
		this->m_pHost->BroadcastMessage(&outPkg, SERVER_TYPE_SERVICE_MANAGER);
	}
	else
	{// less 
		m_isLeader = false;
	}
}

int CGameServer::ProcReqProviderData(SocketHandler* pHandler, NETInputPacket* inputPkg)
{
	if (m_isLeader)
	{
		this->SendAllProviderDataToFollower();
	}

	return 0;
}


int CGameServer::ProcSynProviderData(SocketHandler* pHandler, NETInputPacket* inputPkg)
{
	int svid = inputPkg->ReadInt();
	int score = inputPkg->ReadInt();

	if (svid == TGlobal::_svid)
		return 0; // skip self

	SMITem item;
	item.svid = svid;
	item.score = score;
	m_smList[svid] = item;

	if (m_score > score)
	{
		VoteLeader();
		return 0;
	}

	
	int type_count = inputPkg->ReadInt();
	log_error("m_score=%d,  svid=%d, score=%d,  type_count=%d, ", m_score, svid, score, type_count);

	for (int i = 0; i < type_count; i++)
	{
		int type = inputPkg->ReadInt();
		int item_num = inputPkg->ReadInt();

		ProviderMap& idleItems = m_idleProviderMapTypeList[type];
		ProviderVect& itemVect = m_activeProviderTypeList[type];
		
		for (size_t k = 0; k < itemVect.size(); k++)
		{// clear active items first
			ServerData* pServer = itemVect[k];
			if (NULL != pServer)
				idleItems[pServer->svid] = pServer;
		}
		itemVect.clear();

		for (size_t k = 0; k < item_num; k++)
		{
			int svid = inputPkg->ReadInt();
			ServerData* pServer = NULL;
			if (svid  > 0)
			{//
				ProviderMap::iterator  iter = idleItems.find(svid);
				if (iter != idleItems.end())
				{
					pServer = iter->second;
					idleItems.erase(iter);
				}
			}		
			itemVect.push_back(pServer);
		}


#if 1  //test code
		std::string str_log;
		char str_buf[64] = { 0 };
		snprintf(str_buf, 63, " provider_type=%d, active_count=%d,  ",type, item_num);
		str_log += str_buf;
		for (int i = 0; i < itemVect.size(); i++)
		{
			ServerData* pServer = itemVect[i];
			int svid = 0;
			if (NULL == pServer)
				svid = 0;
			else
				svid = pServer->svid;
			snprintf(str_buf, 63, " [idx=%d,svid=%d,],", i, svid);
			str_log += str_buf;
		}

		log_error(" %s ", str_log.c_str());
#endif
	}
	return 0;
}